package com.ewei.web.crawler.utils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.List;

import org.bson.BsonElement;
import org.bson.BsonObjectId;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.bson.types.ObjectId;

import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;

public class BaseDao<T> implements IBaseDao<T>{
	protected MongoCollection<Document> collection;
	protected Class<T> clz;
	@SuppressWarnings("unchecked")
	public BaseDao(){
		ParameterizedType type = (ParameterizedType)this.getClass().getGenericSuperclass();
		this.clz = (Class<T>)type.getActualTypeArguments()[0];
		collection = MongoDataSource.getCollection(clz.getSimpleName().toLowerCase());
	}
	public long delete(String id) {
		DeleteResult result = 
				collection.deleteOne((Bson) new BsonElement("_id", new BsonObjectId(new ObjectId(id))));
		return result.getDeletedCount();
	}

	public void insert(T t) {
		Document document = createDocument(t);
		collection.insertOne(document);
	}

	public Document find(String id) {
		FindIterable<Document> iterable = collection.find((Bson) new BsonElement("_id", new BsonObjectId(new ObjectId(id))));
		return iterable.first();
	}

	public long update(T t) {
		try{
			Method method = clz.getMethod("getId", new Class<?>[]{});
			String id = (String) method.invoke(t, new Class<?>[]{});
			ObjectId objectId = new ObjectId(id);
			UpdateResult result = collection.updateOne(new Document("_id",objectId),new Document("$set",createDocument(t)));
			return result.getModifiedCount();
		}catch(Exception e){
			throw new RuntimeException(e);
		}
	}
	private Document createDocument(T t){
		Document document = new Document();
		Field[] fields = clz.getDeclaredFields();
		for(int i =0;i<fields.length;i++){
			String name = fields[i].getName();
			if(name.equals("id")) continue;
			char[] nameChar = name.toCharArray();
			if(Character.isLowerCase(nameChar[0])){
				nameChar[0]-=32;
			}
			String nname = new String(nameChar);
			try {
				Method method = clz.getDeclaredMethod("get"+nname,new Class<?>[]{});
				if(null!=method){
					document.append(name, method.invoke(t, new Class<?>[]{}));
				}
			}catch(Exception e){
				throw new RuntimeException(e);
			}
		}
		return document;
	}
}
